package com.baofu.paycore.biz.paycore.handler.impl;

import com.baofu.account.service.facade.model.request.FreezeReqDTO;
import com.baofu.account.service.facade.model.request.UnFreezeReqDTO;
import com.baofu.account.service.facade.model.request.UnFreezeTransferReqDTO;
import com.baofu.clear.service.facade.enums.ClearStatusEnum;
import com.baofu.clear.service.facade.model.WithdrawReqDTO;
import com.baofu.clear.service.facade.model.resp.NotifyDTO;
import com.baofu.paycore.biz.engine.executor.CommandExecutor;
import com.baofu.paycore.biz.engine.result.CommandResult;
import com.baofu.paycore.biz.external.account.AccountService;
import com.baofu.paycore.biz.external.account.converter.AccountRequestConverter;
import com.baofu.paycore.biz.external.clear.ClearQueryService;
import com.baofu.paycore.biz.external.clear.ClearWithdrawService;
import com.baofu.paycore.biz.external.clear.converter.ClearRequestConverter;
import com.baofu.paycore.biz.external.clear.model.ClearFundResBO;
import com.baofu.paycore.biz.model.BackPayBO;
import com.baofu.paycore.biz.notice.ProductHandler;
import com.baofu.paycore.biz.paycore.converter.BO2BOConverter;
import com.baofu.paycore.biz.paycore.handler.BaseHandler;
import com.baofu.paycore.biz.thread.BizCmdAddThread;
import com.baofu.paycore.biz.tools.BuildModel;
import com.baofu.paycore.common.constant.PayCoreConstant;
import com.baofu.paycore.common.enums.*;
import com.baofu.paycore.common.exception.PayCoreBizException;
import com.baofu.paycore.common.utils.DateUtil;
import com.baofu.paycore.common.utils.PayNoGenerateUtil;
import com.baofu.paycore.common.utils.RedisKeyUtil;
import com.baofu.paycore.dal.mapper.FreezeMapper;
import com.baofu.paycore.dal.model.*;
import com.baofu.paycore.manager.cache.RedisManager;
import com.baofu.paycore.manager.converter.BO2DOConverter;
import com.baofu.paycore.manager.model.AccountRespBO;
import com.baofu.paycore.manager.model.ResponseBO;
import com.baofu.paycore.manager.model.UnFreezeTransferRespBO;
import com.baofu.paycore.manager.model.UnFreezeWithdrawRespBO;
import com.baofu.paycore.manager.model.withdraw.WithdrawBO;
import com.baofu.paycore.manager.model.withdraw.WithdrawBankBO;
import com.baofu.paycore.manager.model.withdraw.WithdrawFundBO;
import com.baofu.paycore.manager.storage.impl.*;
import com.baofu.paycore.manager.storer.WithdrawOrderRepository;
import com.baofu.paycore.service.facade.enums.PayCoreErrorCode;
import com.baofu.paycore.service.facade.enums.PayStatusEnums;
import com.baofu.paycore.service.facade.enums.ServiceCodeEnum;
import com.google.common.collect.Maps;
import com.system.commons.exception.BizServiceException;
import com.system.commons.sequence.redis.SequenceFacade;
import com.system.dispatch.CmdManager;
import com.system.dispatch.dal.model.BizCmdDO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.MDC;
import org.slf4j.helpers.SystemMarker;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.task.TaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.support.TransactionTemplate;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * 提现订单处理
 *
 * <p>
 *  1.提现处理
 * </p>
 * User: xin deng  Date: 16/6/3 ProjectName: paycore Version: 1.0
 */
@Slf4j
@Service
public class WithdrawHandler extends BaseHandler<WithdrawBO,NotifyDTO> {

    /**
     * 持久服务
     */
    @Autowired
    private WithdrawOrderRepository withdrawOrderRepository;

    /**
     * 命令执行服务
     */
    @Resource
    protected CommandExecutor commandExecutor;

    /**
     * 账务转账服务
     */
    @Autowired
    private AccountService accountService;

    /**
     * 清分提现服务
     */
    @Autowired
    private ClearWithdrawService clearWithdrawService;

    /**
     * 线程池服务
     */
    @Autowired
    private TaskExecutor taskExecutor;

    /**
     * 命令服务
     */
    @Autowired
    private CmdManager cmdManager;

    /**
     * 提现资金单服务
     */
    @Autowired
    private ClearAccountManager clearAccountManager;

    /**
     * 冻结服务
     */
    @Autowired
    private FreezeManager freezeManager;

    /**
     * 冻结mapper层
     */
    @Autowired
    private FreezeMapper freezeMapper;

    /**
     * 提现主单服务
     */
    @Autowired
    private ClearManager clearManager;

    /**
     * 退款主单服务
     */
    @Autowired
    private RefundManager refundManager;

    /**
     * 退款子单服务
     */
    @Autowired
    private SubRefundManager subRefundManager;

    /**
     * 清分查询服务
     */
    @Autowired
    private ClearQueryService clearQueryService;

    /**
     * 序列生成服务
     */
    @Autowired
    private SequenceFacade sequenceFacade;

    /**
     * spring事物模版
     */
    @Autowired
    private TransactionTemplate transactionTemplate;

    /**
     * 解冻提现
     */
    @Autowired
    private UnfreezeWithdrawHandler unfreezeWithdrawHandler;

    /**
     * 异常日志管理服务
     */
    @Autowired
    private ErrorLogManager errorLogManager;

    @Value("${withdraw.unFreeze.time}")
    private Integer unfreezeTime;

    /**
     * redis服务
     */
    @Autowired
    private RedisManager redisManager;

    /** 发kafka消息服务 */
    @Autowired
    private ProductHandler productHandler;

    /**
     * 提现处理
     *
     * @param withdrawBO    提现参数
     * @return              返回值
     */
    @Override
    public BackPayBO process(WithdrawBO withdrawBO) {
        log.debug("提现开始处理：{}", withdrawBO);
        doExecute(withdrawBO);
        log.info("提现完成结果：{}",withdrawBO);
        //清redis缓存
        redisManager.deleteObject(RedisKeyUtil.buildRedisKey(RedisKeyEnum.WITHDRAW_FREEZE_CODE,
                withdrawBO.getRequestBizNo(), withdrawBO.getRequestOrderNo(), withdrawBO.getRequestSystem()));
        return BO2BOConverter.withdrawBO2BackPayBO(withdrawBO);
    }

    /**
     * 激活领域对象
     *
     * @param orderId 订单ID
     * @return 订单对象
     */
    @Override
    public WithdrawBO activeOrder(String orderId) {
        WithdrawBO withdrawBO = withdrawOrderRepository.load(orderId);
        if(withdrawBO == null){
            log.error("找不到提现订单:{}",orderId);
            throw new PayCoreBizException(PayCoreErrorCode.ORDER_IS_NOT_EXISTED);
        }
        return withdrawBO;
    }

    @Override
    public WithdrawBO queryOrderByPayNo(String payNo) {
        WithdrawBO withdrawBO = withdrawOrderRepository.loadOrderByPayNo(payNo);
        if (withdrawBO == null) {
            log.error("找不到提现订单:{}", payNo);
            throw new PayCoreBizException(PayCoreErrorCode.ORDER_IS_NOT_EXISTED);
        }
        return withdrawBO;
    }

    /**
     * 前置检查
     *
     * @param order 订单
     */
    @Override
    protected void checkBeforeProcess(WithdrawBO order) {
        order.checkStatus();
    }

    /**
     * 提现指令
     * 1.先冻结账户的钱,然后发起调银行提现
     * 2.只有银行返回成功,才会处理后续的流程(解冻转账/有手续费就调账务解冻转账接口)
     * 3.银行明确失败的,解冻之前冻结的账户
     * @param order 单据
     */
    @Override
    protected void processOrders(WithdrawBO order) {

        Map<String,WithdrawFundBO> maps = this.getWithdrawFund(order);
        log.info("提现资金单：{}", maps);

        //1.冻结账户余额
        WithdrawFundBO freezeFund = maps.get(FundTypeEnum.WITHDRAW_FREEZE.getCode());
        if (!accountFreeze(order, freezeFund)) return;

        //2.调用清分提现
        WithdrawBankBO withdrawBankBO = order.getWithdrawBankBO();
        if (!clearWithdraw(order, withdrawBankBO)) return;

        //3.清分提现明确成功,做账务解冻提现,解冻转账服务
        unFreezeWithdraw(order, maps, null);
        //4.单状态处理
        handleStatus(order);
    }

    /**
     * 账务冻结
     *
     * @param withdrawBO        提现单
     * @param withdrawFundBO    提现资金单
     * @return                  true:冻结成功;false:冻结失败
     */
    private boolean accountFreeze(WithdrawBO withdrawBO, WithdrawFundBO withdrawFundBO) {

        FreezeReqDTO freezeReqDTO = AccountRequestConverter.getFreezeReqDTO(withdrawBO, withdrawFundBO);
        AccountRespBO freezeAccount = accountService.freeze(withdrawFundBO.getPayNo(),
                withdrawBO.getServiceCode(), freezeReqDTO);
        this.assertWithdrawFund(withdrawBO, freezeAccount);
        //状态初始化,所有单状态不做处理
        if (PayStatusEnums.INIT.getCode().equals(freezeAccount.getStatus())){
            return false;
        }
        //冻结失败,所有单都置失败
        if (PayStatusEnums.FAIL.getCode().equals(freezeAccount.getStatus())) {
            failFundProcess(withdrawBO,false);
            return false;
        }
        //冻结码放redis缓存
        redisManager.insertObject(freezeAccount.getFreezeCode(),
                RedisKeyUtil.buildRedisKey(RedisKeyEnum.WITHDRAW_FREEZE_CODE, withdrawBO.getRequestBizNo(),
                        withdrawBO.getRequestOrderNo(), withdrawBO.getRequestSystem()));

        return PayStatusEnums.SUCCESS.getCode().equals(freezeAccount.getStatus());
    }

    /**
     * 清分提现处理
     *
     * @param withdrawBO        提现单
     * @param withdrawBankBO    提现银行单
     * @return                  true:提现成功;false:提现失败
     */
    private boolean clearWithdraw(WithdrawBO withdrawBO, WithdrawBankBO withdrawBankBO) {

        WithdrawReqDTO withdrawReqDTO = ClearRequestConverter.convertToWithdrawDTO(withdrawBO, withdrawBankBO);
        ClearFundResBO clearFundResBO = clearWithdrawService.withdraw(withdrawReqDTO,ServiceCodeEnum.WITHDRAW.getCode());
        //结果集处理
        this.bankResult(withdrawBO, clearFundResBO);

        if (clearFundResBO.isRealFlag() && PayStatusEnums.FAIL.getCode().equals(clearFundResBO.getPayStat())) {
            //银行单失败,其他未处理资金单也改为失败
            bankFailProcessor(withdrawBO);
            //异步插入dispatch,做解冻处理
            this.addBizCmd(withdrawBO.getPayNo(), withdrawBO.getServiceCode(),
                    BizCmdTypeEnum.ACC_UNFREEZE.getCode(), 1);
        }

        return clearFundResBO.isRealFlag() && PayStatusEnums.SUCCESS.getCode().equals(clearFundResBO.getPayStat());
    }

    /**
     * 请求银行单失败处理状态
     *
     * @param withdrawBO    提现单
     */
    private void bankFailProcessor(WithdrawBO withdrawBO){
        withdrawBO.setStatus(PayStatusEnums.FAIL.getCode());
        withdrawBO.getWithdrawFundBO().forEach(withdrawFundBO -> {
                    if (!FundTypeEnum.WITHDRAW_FREEZE.getCode().equals(withdrawFundBO.getFundType())) {
                        withdrawFundBO.setStatus(PayStatusEnums.FAIL.getCode());
                    }
                }
        );
    }
    /**
     * 添加命令
     *
     * @param payNo     单号
     * @param service   服务
     * @param bizType   业务类型
     */
    private void addBizCmd(String payNo, String service, String bizType, int maxRetryTimes) {
        String bizId = service.concat(PayCoreConstant.BASE_CMD_SEPARATOR).concat(payNo);
        BizCmdDO bizCmdDO = BuildModel.buildBizCmd(bizId, bizType, DateUtil.addSeconds(new Date(), unfreezeTime),
                maxRetryTimes, MDC.get(SystemMarker.TRACE_LOG_ID));
        BizCmdAddThread thread = new BizCmdAddThread(bizCmdDO, cmdManager);
        taskExecutor.execute(thread);
    }

    /**
     * 解冻提现
     *
     * @param withdrawBO    提现单
     * @param maps          集合
     */
    private void unFreezeWithdraw(WithdrawBO withdrawBO, Map<String, WithdrawFundBO> maps, String eventNo) {
        //冻结码
        String freezeCode = withdrawBO.getWithdrawFund(withdrawBO.getWithdrawFundBO(),
                FundTypeEnum.WITHDRAW_FREEZE.getCode()).getFreezeCode();
        //没值时查redis缓存
        if (StringUtils.isEmpty(freezeCode)){
            freezeCode = redisManager.queryObjectByKey(RedisKeyUtil.buildRedisKey(RedisKeyEnum.WITHDRAW_FREEZE_CODE,
                    withdrawBO.getRequestBizNo(), withdrawBO.getRequestOrderNo(), withdrawBO.getRequestSystem()),
                    String.class);
        }
        log.debug("提现 冻结码:{}", freezeCode);
        //获取解冻提现单
        WithdrawFundBO unFreezeWithdraw = maps.get(FundTypeEnum.UNFREEZE_WITHDRAW.getCode());
        unFreezeWithdraw.setFreezeCode(freezeCode);
        if (StringUtils.isNotEmpty(eventNo)) unFreezeWithdraw.setEventNo(eventNo);
        //调用账务解冻提现
        UnFreezeWithdrawRespBO respBO = accountService.unFreezeWithdraw(withdrawBO, unFreezeWithdraw);
        this.unFreezeWithdrawResult(withdrawBO, respBO);
        if(!Objects.equals(PayStatusEnums.SUCCESS.getCode(),respBO.getStatus())){
            log.debug("解冻提现未成功:{}",respBO.getStatus());
            return;
        }

        //解冻转账
        WithdrawFundBO unFreezeTransfer = maps.get(FundTypeEnum.FEE.getCode());
        if (unFreezeTransfer == null) return;
        //冻结码赋值
        unFreezeTransfer.setFreezeCode(freezeCode);
        //手续费解冻转账
        this.unFreezeTransfer(withdrawBO, unFreezeTransfer);
    }

    /**
     * 解冻转账处理
     *
     * @param withdrawBO        提现单
     * @param withdrawFundBO    提现资金单
     */
    private void unFreezeTransfer(WithdrawBO withdrawBO, WithdrawFundBO withdrawFundBO){
        UnFreezeTransferReqDTO transferReqDTO =
                AccountRequestConverter.getUnFreezeTransferByFundBO(withdrawFundBO, withdrawBO);
        //调账务解冻转账
        UnFreezeTransferRespBO respBO = accountService.unFreezeTransfer(withdrawBO.getPayNo(),
                withdrawBO.getServiceCode(), transferReqDTO);
        //响应结果处理
        unFreezeTransferResult(withdrawBO, respBO);
    }

    /**
     * 资金单赋值
     *
     * @param order             资金单
     * @param accountRespBO     账务响应
     */
    private void assertWithdrawFund(WithdrawBO order, AccountRespBO accountRespBO) {
        order.setRealFlag(accountRespBO.isRealRtn());
        //获取提现冻结单
        WithdrawFundBO withdrawFundBO = order.getWithdrawFund(order.getWithdrawFundBO(),
                FundTypeEnum.WITHDRAW_FREEZE.getCode());
        withdrawFundBO.setStatus(accountRespBO.getStatus());
        withdrawFundBO.setFreezeCode(accountRespBO.getFreezeCode());
        withdrawFundBO.setTransDate(accountRespBO.getAccDate());
        withdrawFundBO.setTransReceiptNo(accountRespBO.getReceiptNo());
        withdrawFundBO.setErrorCode(accountRespBO.getErrorCode());
        withdrawFundBO.setErrorReason(accountRespBO.getErrorMsg());
        order.setErrorCode(accountRespBO.getErrorCode());
        order.setErrorMsg(accountRespBO.getErrorMsg());
    }

    /**
     * 银行单失败处理
     *
     * @param order             订单
     * @param clearFundResBO    银行处理结果
     */
    private void bankResult(WithdrawBO order, ClearFundResBO clearFundResBO){
        order.setRealFlag(clearFundResBO.isRealFlag());
        order.getWithdrawBankBO().setStatus(clearFundResBO.getPayStat());
        order.getWithdrawBankBO().setTransDate(clearFundResBO.getResponseDate());
        order.getWithdrawBankBO().setErrorCode(clearFundResBO.getErrorCode());
        order.getWithdrawBankBO().setErrorReason(clearFundResBO.getErrorMsg());
        order.getWithdrawBankBO().setTransReceiptNo(clearFundResBO.getResponseNo());
        order.setErrorMsg(clearFundResBO.getErrorMsg());
        order.setErrorCode(clearFundResBO.getErrorCode());
        order.getWithdrawFund(order.getWithdrawFundBO(),
                FundTypeEnum.UNFREEZE_WITHDRAW.getCode()).setEventNo(clearFundResBO.getEventNo());
    }

    /**
     * 解冻提现结果处理
     *
     * @param order     提现单
     * @param respBO    解冻提现响应
     */
    private void unFreezeWithdrawResult(WithdrawBO order, UnFreezeWithdrawRespBO respBO) {
        order.setRealFlag(respBO.isRealRtn());
        //获取解冻提现单
        WithdrawFundBO withdrawFundBO = order.getWithdrawFund(order.getWithdrawFundBO(),
                FundTypeEnum.UNFREEZE_WITHDRAW.getCode());
        BO2BOConverter.unFreezeWithdrawResult(withdrawFundBO, respBO);
    }

    /**
     * 解冻转账单结果
     *
     * @param order     提现单
     * @param respBO    解冻转账单结果
     */
    private void unFreezeTransferResult(WithdrawBO order,UnFreezeTransferRespBO respBO){
        order.setRealFlag(respBO.isRealRtn());
        //获取手续费单
        WithdrawFundBO withdrawFundBO = order.getWithdrawFund(order.getWithdrawFundBO(),
                FundTypeEnum.FEE.getCode());
        BO2BOConverter.unFreezeTransferResult(withdrawFundBO, respBO);
    }
    /**
     * 处理主单状态
     *
     * @param withdrawBO    提现单
     */
    private void handleStatus(WithdrawBO withdrawBO) {

        List<WithdrawFundBO> withdrawFundBOs = withdrawBO.getWithdrawFundBO();
        //银行单状态
        String bankStatus = withdrawBO.getWithdrawBankBO().getStatus();
        withdrawBO.setStatus(bankStatus);
        //针对提现业务,银行提现结果已经成功了,为不引起资金损失,一定是要账务成功的
        //若账务调用返回失败,给上层处理中,后面大总管确认后手动去补,使账务成功
        for (WithdrawFundBO withdrawFundBO : withdrawFundBOs) {
            if (PayStatusEnums.FAIL.getCode().equals(withdrawFundBO.getStatus()) &&
                    PayStatusEnums.SUCCESS.getCode().equals(bankStatus)) {
                withdrawBO.setErrorCode(withdrawFundBO.getErrorCode());
                withdrawBO.setErrorMsg(withdrawFundBO.getErrorReason());
                withdrawBO.setStatus(PayStatusEnums.INIT.getCode());
                break;
            }
            if (PayStatusEnums.INIT.getCode().equals(withdrawFundBO.getStatus())){
                withdrawBO.setStatus(PayStatusEnums.INIT.getCode());
                break;
            }
        }

    }

    /**
     * 失败流程处理
     *  冻结账户失败了,主单和其他资金单全是失败
     * @param withdrawBO    提现单
     * @param afterClear    是否在清分流程后 清分流程后的单子不处理冻结单,由异步任务处理异常解冻流程
     */
    private void failFundProcess(WithdrawBO withdrawBO, boolean afterClear) {
        withdrawBO.setStatus(PayStatusEnums.FAIL.getCode());
        withdrawBO.getWithdrawBankBO().setStatus(PayStatusEnums.FAIL.getCode());
        for (WithdrawFundBO rechargeFundBO : withdrawBO.getWithdrawFundBO()) {
            if (afterClear && rechargeFundBO.getFundType().equals(FundTypeEnum.WITHDRAW_FREEZE.getCode())) {
                continue;
            }
            rechargeFundBO.setStatus(PayStatusEnums.FAIL.getCode());
        }
    }

    /**
     * 持久化对象
     *
     * @param order 单据
     */
    @Override
    protected void reStore(WithdrawBO order) {
        withdrawOrderRepository.update(order);
    }

    /**
     * 指令完成后处理
     *
     * @param order     领域模型
     * @param cmdResult 指令处理结果
     */
    @Override
    protected void processAfter(WithdrawBO order, Map<String, CommandResult> cmdResult) {

    }

    /**
     * 补单订单状态校验
     * @param withdrawBO  提现单
     */
    public void checkRetryStatus(WithdrawBO withdrawBO) {
        WithdrawFundBO withdrawFundBO=withdrawBO.getWithdrawFund(withdrawBO.getWithdrawFundBO(), FundTypeEnum.WITHDRAW_FREEZE.getCode());
        if(!PayStatusEnums.SUCCESS.getCode().equals(withdrawFundBO.getStatus())){
            throw new BizServiceException(PayCoreErrorCode.ORDER_START_NOT_SUCCESS);
        }
    }

    /**
     * 订单补单具体操作
     */
    public String processRetry(WithdrawBO withdrawBO){
        WithdrawFundBO unfreezeWithdrawFundBO=withdrawBO.getWithdrawFund(withdrawBO.getWithdrawFundBO(), FundTypeEnum.UNFREEZE_WITHDRAW.getCode());
        WithdrawFundBO freezeWithdraw=withdrawBO.getWithdrawFund(withdrawBO.getWithdrawFundBO(), FundTypeEnum.WITHDRAW_FREEZE.getCode());
        if(PayStatusEnums.FAIL.getCode().equals(unfreezeWithdrawFundBO.getStatus())){
            //订单入表
            withdrawOrderRepository.addRetryOrder(unfreezeWithdrawFundBO,withdrawBO.getOperator());
            unfreezeWithdrawFundBO.setFreezeCode(freezeWithdraw.getFreezeCode());
            //调用账务解冻提现
            UnFreezeWithdrawRespBO respBO = accountService.unFreezeWithdraw(withdrawBO, unfreezeWithdrawFundBO);
            BO2BOConverter.unFreezeWithdrawResult(unfreezeWithdrawFundBO, respBO);
        }

        //解冻转账
        WithdrawFundBO unFreezeTransfer = withdrawBO.getWithdrawFund(withdrawBO.getWithdrawFundBO(),FundTypeEnum.FEE.getCode());
        if (unFreezeTransfer != null&&PayStatusEnums.FAIL.getCode().equals(unFreezeTransfer.getStatus())) {
            //订单入表
            withdrawOrderRepository.addRetryOrder(unFreezeTransfer,withdrawBO.getOperator());
            //冻结码赋值
            unFreezeTransfer.setFreezeCode(freezeWithdraw.getFreezeCode());
            //手续费解冻转账
            feeRetry(withdrawBO,unFreezeTransfer);
        }
        handleRetryStatus(withdrawBO,unFreezeTransfer,unfreezeWithdrawFundBO);
        withdrawOrderRepository.updateRetry(withdrawBO);
        if(PayStatusEnums.SUCCESS.getCode().equals(withdrawBO.getStatus())){
            //发送消息
            productHandler.sendKafkaMsg(BO2BOConverter.getPayMessageDTO(withdrawBO));
        }
        return withdrawBO.getStatus();
    }

    private void handleRetryStatus(WithdrawBO withdrawBO, WithdrawFundBO unFreezeTransfer, WithdrawFundBO unfreezeWithdrawFundBO) {
        withdrawBO.getWithdrawFundBO().clear();
        if(unFreezeTransfer!=null)
        withdrawBO.getWithdrawFundBO().add(unFreezeTransfer);
        if(unfreezeWithdrawFundBO!=null)
        withdrawBO.getWithdrawFundBO().add(unfreezeWithdrawFundBO);
        List<WithdrawFundBO> withdrawFundBOs = withdrawBO.getWithdrawFundBO();
        withdrawBO.setStatus(PayStatusEnums.SUCCESS.getCode());
        //针对提现业务,银行提现结果已经成功了,为不引起资金损失,一定是要账务成功的
        //若账务调用返回失败,给上层处理中,后面大总管确认后手动去补,使账务成功
        for (WithdrawFundBO withdrawFundBO : withdrawFundBOs) {
            if (PayStatusEnums.FAIL.getCode().equals(withdrawFundBO.getStatus())) {
                withdrawBO.setErrorCode(withdrawFundBO.getErrorCode());
                withdrawBO.setErrorMsg(withdrawFundBO.getErrorReason());
                withdrawBO.setStatus(PayStatusEnums.FAIL.getCode());
                break;
            }
            if (PayStatusEnums.INIT.getCode().equals(withdrawFundBO.getStatus())){
                withdrawBO.setStatus(PayStatusEnums.INIT.getCode());
                break;
            }
        }
    }

    /**
     * 提现手续费重发
     *
     * @param withdrawBO        提现单
     * @param unFreezeTransfer    提现资金单
     */
    private void feeRetry(WithdrawBO withdrawBO, WithdrawFundBO unFreezeTransfer){
        //手续费解冻转账
        UnFreezeTransferReqDTO transferReqDTO =
                AccountRequestConverter.getUnFreezeTransferByFundBO(unFreezeTransfer, withdrawBO);
        //调账务解冻转账
        UnFreezeTransferRespBO unFreezeTransferRespBO = accountService.unFreezeTransfer(withdrawBO.getPayNo(),
                withdrawBO.getServiceCode(), transferReqDTO);
        BO2BOConverter.unFreezeTransferResult(unFreezeTransfer, unFreezeTransferRespBO);
    }

    /**
     * 资金单集合转换
     *
     * @param withdrawBO    提现单
     * @return              map
     */
    private Map<String, WithdrawFundBO> getWithdrawFund(WithdrawBO withdrawBO) {
        Map<String, WithdrawFundBO> map = Maps.newHashMap();
        for (WithdrawFundBO fundBO : withdrawBO.getWithdrawFundBO()) {
            map.put(fundBO.getFundType(), fundBO);
        }
        return map;
    }

    /**
     * 回调
     *
     * @return 回调处理响应
     */
    @Override
    public WithdrawBO callBack(NotifyDTO callBackDTO) {
        //获取提现单信息
        WithdrawBO withdrawBO = activeOrder(callBackDTO.getRequestBizNo());
        WithdrawFundBO freezeFund = withdrawBO.getWithdrawFund(withdrawBO.getWithdrawFundBO(),
                FundTypeEnum.WITHDRAW_FREEZE.getCode());
        if (!PayStatusEnums.SUCCESS.getCode().equals(freezeFund.getStatus())){
            log.warn("冻结单状态未成功,status:{}", freezeFund.getStatus());
            return null;
        }
        withdrawBO.setTradeLogId(callBackDTO.getTradeLogId());
        //提现订单状态判断
        if (StringUtils.equals(withdrawBO.getStatus(), PayStatusEnums.SUCCESS.getCode()) ||
                StringUtils.equals(withdrawBO.getStatus(), PayStatusEnums.FAIL.getCode())) {
            log.warn("提现回调 主单状态已处理完成 重复回调了 记录异常单 主单状态:{}", withdrawBO.getStatus());
            throw new BizServiceException(PayCoreErrorCode.CALLBACK_REPEAT_EXCEPTION);
        }
        //判断清分单状态
        if (!dealBankFund(callBackDTO, withdrawBO)) {
            //更新订单信息
            reStore(withdrawBO);
            return withdrawBO;
        }
        if(ServiceCodeEnum.WITHDRAW.getCode().equals(withdrawBO.getServiceCode())){
            //推进订单
            advance(withdrawBO, callBackDTO.getEventNo());
        }else if(ServiceCodeEnum.ISSUE_WITHDRAW.getCode().equals(withdrawBO.getServiceCode())){
            unfreezeWithdrawHandler.advance(withdrawBO,callBackDTO.getEventNo());
        }
        //更新订单信息
        reStore(withdrawBO);

        return withdrawBO;
    }

    /**
     * 提现单状态推进
     *
     * @param withdrawBO    提现单
     */
    private void advance(WithdrawBO withdrawBO, String eventNo) {
        Map<String,WithdrawFundBO> maps = this.getWithdrawFund(withdrawBO);
        //解冻提现
        this.unFreezeWithdraw(withdrawBO, maps, eventNo);

        handleStatus(withdrawBO);
    }

    /**
     * 处理银行订单
     *
     * @param callBackDTO           回调参数
     * @param withdrawBO            提现订单
     * @return                      处理结果
     */
    private boolean dealBankFund(NotifyDTO callBackDTO, WithdrawBO withdrawBO) {
        withdrawBO.setErrorCode(callBackDTO.getRespCode());
        withdrawBO.setErrorMsg(callBackDTO.getRespDesc());
        withdrawBO.setRealFlag(Objects.equals(callBackDTO.getStatus(), ClearStatusEnum.F.getCode()) ||
                Objects.equals(callBackDTO.getStatus(), ClearStatusEnum.S.getCode()));
        if (ClearStatusEnum.S.getCode().equals(callBackDTO.getStatus())) {
            withdrawBO.setStatus(PayStatusEnums.SUCCESS.getCode());
            withdrawBO.getWithdrawBankBO().setStatus(PayStatusEnums.SUCCESS.getCode());
            withdrawBO.getWithdrawBankBO().setFundChannel(callBackDTO.getFundChannel());
            withdrawBO.getWithdrawBankBO().setFundSubChannel(callBackDTO.getCounterNo());
            withdrawBO.getWithdrawBankBO().setErrorCode(callBackDTO.getRespCode());
            withdrawBO.getWithdrawBankBO().setErrorReason(callBackDTO.getRespDesc());
            return true;
        }
        //清分状态转换支付状态
        if (ClearStatusEnum.I.getCode().equals(callBackDTO.getStatus()) ||
                ClearStatusEnum.P.getCode().equals(callBackDTO.getStatus())) {
            withdrawBO.setStatus(PayStatusEnums.INIT.getCode());
            return false;
        }
        if (ClearStatusEnum.F.getCode().equals(callBackDTO.getStatus())) {
            failFundProcessor(withdrawBO, callBackDTO);
            if(!ServiceCodeEnum.ISSUE_WITHDRAW.getCode().equals(withdrawBO.getServiceCode())){
                //异步插入dispatch,做解冻处理
                this.addBizCmd(withdrawBO.getPayNo(), withdrawBO.getServiceCode(),
                        BizCmdTypeEnum.ACC_UNFREEZE.getCode(), 1);
            }
            return false;
        }
        log.error("未知的订单状态:{}", callBackDTO.getStatus());
        throw new PayCoreBizException(PayCoreErrorCode.BANK_REQUEST_ERROR, "未知的订单状态");
    }

    /**
     * 银行单返回失败处理流程
     *
     * @param withdrawBO    提现单
     * @param callBackDTO   回调
     */
    private void failFundProcessor(WithdrawBO withdrawBO, NotifyDTO callBackDTO){

        withdrawBO.getWithdrawBankBO().setStatus(PayStatusEnums.FAIL.getCode());
        withdrawBO.getWithdrawBankBO().setErrorReason(callBackDTO.getRespDesc());
        withdrawBO.getWithdrawBankBO().setErrorCode(callBackDTO.getRespCode());
        withdrawBO.getWithdrawBankBO().setTransDate(callBackDTO.getResponseDate());
        this.failFundProcess(withdrawBO,true);
    }

    /**
     * 提现解冻
     *
     * @param withdrawBO    提现单
     */
    public void withdrawUnFreeze(WithdrawBO withdrawBO) {

        WithdrawBankBO withdrawBankBO = withdrawBO.getWithdrawBankBO();
        if (!PayStatusEnums.FAIL.getCode().equals(withdrawBankBO.getStatus())) {
            log.error("提现 账务解冻失败 清分银行不是失败 状态:{}", withdrawBankBO.getStatus());
            throw new BizServiceException(PayCoreErrorCode.CLEAR_BANK_STATUS_NOT_FAIL);
        }
        //提现冻结单
        WithdrawFundBO freezeFundBO = withdrawBO.getWithdrawFund(withdrawBO.getWithdrawFundBO(),
                FundTypeEnum.WITHDRAW_FREEZE.getCode());
        if (!PayStatusEnums.SUCCESS.getCode().equals(freezeFundBO.getStatus())) {
            log.error("提现 账务解冻失败 提现冻结单不是成功 状态:{}", freezeFundBO.getStatus());
            throw new BizServiceException(PayCoreErrorCode.CLEAR_ACC_STATUS_NOT_SUC);
        }

        //异常提现解冻单
        WithdrawFundBO exUnfreezeFundBO = loadExWithdrawFund(withdrawBO);

        UnFreezeReqDTO unFreezeReqDTO = AccountRequestConverter.getUnFreezeReqDTO(exUnfreezeFundBO, withdrawBO);
        AccountRespBO accountRespBO =
                accountService.unFreeze(withdrawBO.getPayNo(), withdrawBO.getServiceCode(), unFreezeReqDTO);
        if (!accountRespBO.isRealRtn() || PayStatusEnums.INIT.getCode().equals(accountRespBO.getStatus())){
            ErrorLogDO errorLogDO = BuildModel.buildErrorLog(withdrawBO.getPayNo(), null,
                    BizCmdTypeEnum.ACC_UNFREEZE.getCode(), ServiceCodeEnum.WITHDRAW.getCode(),
                    accountRespBO.getErrorCode(), accountRespBO.getErrorMsg(), "账务解冻未成功");
            errorLogManager.addOrder(errorLogDO);
            return;
        }
        //状态处理
        unfreezeStatusProcessor(withdrawBO, freezeFundBO, accountRespBO);
    }

    private WithdrawFundBO loadExWithdrawFund(WithdrawBO withdrawBO) {
        //异常提现解冻单
        WithdrawFundBO freezeFundBO = withdrawBO.getWithdrawFund(withdrawBO.getWithdrawFundBO(),
                FundTypeEnum.EX_UNFREEZE_WITHDRAW.getCode());
        if(freezeFundBO==null){
            freezeFundBO = addExWithdrawFund(withdrawBO);
        }
        if (!PayStatusEnums.INIT.getCode().equals(freezeFundBO.getStatus())) {
            log.error("提现 账务解冻失败 异常提现解冻单不为初始 状态:{}", freezeFundBO.getStatus());
            throw new BizServiceException(PayCoreErrorCode.CLEAR_ACC_STATUS_NOT_INIT);
        }
        return freezeFundBO;
    }

    private WithdrawFundBO addExWithdrawFund(WithdrawBO withdrawBO) {

        WithdrawFundBO freezeBO = withdrawBO.getWithdrawFund(withdrawBO.getWithdrawFundBO(),FundTypeEnum.WITHDRAW_FREEZE.getCode());

        WithdrawFundBO exUnfreezeBO = BO2BOConverter.freezeBO2ExUnfreezeBO(freezeBO);
        //资金明细No
        exUnfreezeBO.setFundDetailNo(sequenceFacade.getUniqueSeq());
        //解冻单号
        exUnfreezeBO.setUnfreezeNo(sequenceFacade.getUniqueSeq());
        //支付单号
        exUnfreezeBO.setPayNo(PayNoGenerateUtil.payNoGenerate(sequenceFacade, ServiceCodeEnum.UNFREEZE.getCode()));

        freezeManager.addOrder(BO2DOConverter.getFreezeDO(withdrawBO,exUnfreezeBO,UpdateUser.SYS.getUserName()));

        withdrawBO.getWithdrawFundBO().add(exUnfreezeBO);

        return exUnfreezeBO;
    }

    private void unfreezeStatusProcessor(WithdrawBO withdrawBO, WithdrawFundBO withdrawFundBO,
                                          AccountRespBO accountRespBO){
        String payNo = PayNoGenerateUtil.payNoGenerate(sequenceFacade, ServiceCodeEnum.REFUND.getCode());
        //退款主单
        RefundDO refundDO = BO2DOConverter.getRefundDOByWithdrawBO(withdrawBO, withdrawFundBO);
        refundDO.setPayNo(payNo);
        refundDO.setStatus(accountRespBO.getStatus());
        //退款子单
        SubRefundDO subRefundDO = BO2DOConverter.getSubRefundDOBySubWithdraw(withdrawFundBO);
        subRefundDO.setPayNo(payNo);
        subRefundDO.setFundDetailNo(sequenceFacade.getUniqueSeq());
        subRefundDO.setStatus(accountRespBO.getStatus());
        subRefundDO.setErrorCode(accountRespBO.getErrorCode());
        subRefundDO.setErrorReason(accountRespBO.getErrorMsg());
        subRefundDO.setTransDate(accountRespBO.getAccDate());
        subRefundDO.setTransReceiptNo(accountRespBO.getReceiptNo());
        FreezeDO freezeDO = new FreezeDO();
        if (PayStatusEnums.SUCCESS.getCode().equals(accountRespBO.getStatus())){
            //冻结资金单
            freezeDO.setPayNo(withdrawBO.getPayNo());
            freezeDO.setDealAmt(withdrawFundBO.getAmt());
        }
        WithdrawFundBO unfreezeBO = withdrawBO.getWithdrawFund(withdrawBO.getWithdrawFundBO(),
                FundTypeEnum.EX_UNFREEZE_WITHDRAW.getCode());
        unfreezeBO.setStatus(accountRespBO.getStatus());
        unfreezeBO.setTransDate(accountRespBO.getAccDate());
        unfreezeBO.setTransReceiptNo(accountRespBO.getReceiptNo());
        unfreezeBO.setErrorCode(accountRespBO.getErrorCode());
        unfreezeBO.setErrorReason(accountRespBO.getErrorMsg());

        buildProcess(refundDO, subRefundDO, freezeDO,
                BO2DOConverter.getFreezeDO(withdrawBO,unfreezeBO,UpdateUser.SYS.getUserName()));
    }

    /**
     * 处理解冻相关单的状态
     *
     * @param refundDO          退款主单
     * @param subRefundDO       退款子单
     * @param freezeDO    提现资金单
     * @param unFreezeDO        异常提现资金解冻单
     */
    private void buildProcess(RefundDO refundDO, SubRefundDO subRefundDO, FreezeDO freezeDO,FreezeDO unFreezeDO){

        transactionTemplate.execute(status -> {
            if (freezeDO != null){
                freezeMapper.updateDealAmt(freezeDO);
            }
            if(unFreezeDO!=null){
                freezeManager.modifyOrder(unFreezeDO);
            }
            refundManager.addOrder(refundDO);
            subRefundManager.addOrder(subRefundDO);
            return true;
        });
    }

    /**
     * 需重试接口 对内部资金单的重试（订单状态推进）
     *
     * @param withdrawBO  提现订单对象
     * @return ResponseBO
     * @throws RuntimeException 出现异常时表示重试没有成功（子类方法实现中不可捕获异常）
     */
    public ResponseBO dalInnerFundProc(WithdrawBO withdrawBO) throws RuntimeException {
        ResponseBO responseBO = null;
        WithdrawBankBO withdrawBankBO = withdrawBO.getWithdrawBankBO();
        List<WithdrawFundBO> withdrawFundBOs = withdrawBO.getWithdrawFundBO();
        //获取冻结单
        WithdrawFundBO withdrawFund =
                withdrawBO.getWithdrawFund(withdrawFundBOs, FundTypeEnum.WITHDRAW_FREEZE.getCode());
        if (PayStatusEnums.FAIL.getCode().equals(withdrawFund.getStatus())){
            log.error("提现重试接口 单号:{}, 冻结单状态:{}", withdrawFund.getPayNo(), withdrawFund.getStatus());
            return new ResponseBO(withdrawBO.getStatus(), withdrawBO.getErrorCode(),
                    withdrawBO.getErrorMsg(), withdrawBO.getPayNo(), withdrawBO.isRealFlag());
        }
        //若提现冻结单未成功且银行单初始化状态,走整个流程,循环结束
        if (PayStatusEnums.INIT.getCode().equals(withdrawFund.getStatus())){
            log.info("提现冻结单payNo:{},状态:{},未成功,走整个流程", withdrawFund.getPayNo(), withdrawFund.getStatus());
            this.processOrders(withdrawBO);
            withdrawOrderRepository.update(withdrawBO);
            return new ResponseBO(withdrawBO.getStatus(), withdrawBO.getErrorCode(),
                    withdrawBO.getErrorMsg(), withdrawBO.getPayNo(), withdrawBO.isRealFlag());
        }
        //获取冻结码
        String freezeCode = withdrawFund.getFreezeCode();
        for (WithdrawFundBO withdrawFundBO : withdrawFundBOs){
            //校验
            if (!validFundStatus(withdrawBankBO, withdrawFundBO)) continue;

            FundTypeEnum fundType = FundTypeEnum.explain(withdrawFundBO.getFundType());
            if (null == fundType) continue;

            withdrawFundBO.setFreezeCode(freezeCode);
            switch (fundType){
                case UNFREEZE_WITHDRAW:
                    responseBO = retryUnfreezeWithdraw(withdrawBO, withdrawFundBO);
                    break;
                case FEE:
                    responseBO = retryUnfreezeTransfer(withdrawBO, withdrawFundBO);
                    break;
                default:
                    log.error("暂不支持此业务：{}", fundType);
                    throw new PayCoreBizException(PayCoreErrorCode.NOT_IN_SERVICE);
            }
            if (null == responseBO){
                log.error("提现重试 资金单类型:{} 资金单号:{} 资金单状态:{}", withdrawFundBO.getFundType(),
                        withdrawFundBO.getFundDetailNo(), withdrawFundBO.getStatus());
                break;
            }

            if (!validateContinue(responseBO.isRealFlag(), responseBO.getStatus())){
                log.error("提现重试 失败 请求服务类型:{} 资金单号:{} 资金单类型:{} 转账处理状态:{}", withdrawBO.getServiceCode(),
                        responseBO.getRequestNo(), withdrawFundBO.getFundType(), responseBO.getStatus());
                break;
            }
        }
        //处理主单状态
        handlerWithdrawOrder(responseBO, withdrawBO);
        return responseBO;
    }

    /**
     * 重试解冻提现单
     *
     * @param withdrawBO        提现主单
     * @param withdrawFundBO    解冻提现单
     * @return                  ResponseBO
     */
    private ResponseBO retryUnfreezeWithdraw(WithdrawBO withdrawBO, WithdrawFundBO withdrawFundBO){

        UnFreezeWithdrawRespBO respBO = accountService.unFreezeWithdraw(withdrawBO, withdrawFundBO);
        BO2BOConverter.unFreezeWithdrawResult(withdrawFundBO, respBO);

        return getResponseBO(respBO, withdrawFundBO);
    }
    /**
     * 重试解冻转账单
     *
     * @param withdrawBO        提现主单
     * @param withdrawFundBO    解冻提现单
     * @return                  ResponseBO
     */
    private ResponseBO retryUnfreezeTransfer(WithdrawBO withdrawBO, WithdrawFundBO withdrawFundBO){
        UnFreezeTransferReqDTO transferReqDTO =
                AccountRequestConverter.getUnFreezeTransferByFundBO(withdrawFundBO, withdrawBO);
        //调账务解冻转账
        UnFreezeTransferRespBO respBO = accountService.unFreezeTransfer(withdrawBO.getPayNo(),
                withdrawBO.getServiceCode(), transferReqDTO);

        return getResponseBO(respBO, withdrawFundBO);
    }

    private ResponseBO getResponseBO(AccountRespBO respBO, WithdrawFundBO withdrawFundBO){

        clearAccountManager.modifyOrder(BO2DOConverter.getClearAccountByFundBO(withdrawFundBO));

        return new ResponseBO(respBO.getStatus(), respBO.getErrorCode(),respBO.getErrorMsg(), respBO.getAccDate(),
                respBO.getReceiptNo(), withdrawFundBO.getFundDetailNo(), respBO.getFreezeCode(), respBO.isRealRtn());
    }

    /**
     * 处理提现单
     *
     * @param responseBO    响应对象
     */
    private void handlerWithdrawOrder(ResponseBO responseBO, WithdrawBO withdrawBO){
        if (responseBO == null || !responseBO.isRealFlag()){
            return;
        }
        ClearDO clearDO = new ClearDO();
        clearDO.setUpdatedBy(UpdateUser.SYS.getUserName());
        clearDO.setStatus(responseBO.getStatus());
        clearDO.setPayNo(withdrawBO.getPayNo());
        clearManager.modifyOrder(clearDO);
    }
    /**
     * 校验资金单状态
     *
     * @param withdrawBankBO    银行单
     * @param withdrawFundBO    提现资金单
     * @return                  true;false
     */
    private boolean validFundStatus(WithdrawBankBO withdrawBankBO, WithdrawFundBO withdrawFundBO) {
        if (PayStatusEnums.SUCCESS.getCode().equals(withdrawFundBO.getStatus())) {
            log.debug("提现重试 资金单类型:{} 资金单号:{} 资金单状态:{}", withdrawFundBO.getFundType(),
                    withdrawFundBO.getFundDetailNo(), withdrawFundBO.getStatus());
            return false;
        }
        if (PayStatusEnums.FAIL.getCode().equals(withdrawFundBO.getStatus())) {
            log.error("提现重试 资金单类型:{} 资金单号:{} 资金单状态:{}", withdrawFundBO.getFundType(),
                    withdrawFundBO.getFundDetailNo(), withdrawFundBO.getStatus());
            return false;
        }

        //解冻提现单
        if (FundTypeEnum.UNFREEZE_WITHDRAW.getCode().equals(withdrawFundBO.getStatus()) &&
                !PayStatusEnums.SUCCESS.getCode().equals(withdrawBankBO.getStatus())) {
            log.error("提现重试 银行单未成功 资金单类型:{} 银行单号:{} 银行单状态:{}", withdrawFundBO.getFundType(),
                    withdrawBankBO.getFundDetailNo(), withdrawBankBO.getStatus());
            return false;
        }
        //解冻转账手续费单
        if (FundTypeEnum.FEE.getCode().equals(withdrawFundBO.getStatus()) &&
                !PayStatusEnums.SUCCESS.getCode().equals(withdrawBankBO.getStatus())) {
            log.error("提现重试 银行单未成功 资金单类型:{} 银行单号:{} 银行单状态:{}", withdrawFundBO.getFundType(),
                    withdrawBankBO.getFundDetailNo(), withdrawBankBO.getStatus());
            return false;
        }
        return true;
    }

    /**
     * 提现清分超时处理
     *
     * @param requestOrderNo    请求单号
     * @return                  Response
     */
    public ResponseBO withdrawTimeOut(WithdrawBO withdrawBO, String requestOrderNo) {
        ClearFundResBO clearFundResBO = clearQueryService.queryWithdrawByRequestOrderNo(withdrawBO.getPayNo(),
                requestOrderNo);
        if (!clearFundResBO.isRealFlag()){
            return new ResponseBO(PayStatusEnums.INIT.getCode(), clearFundResBO.getErrorCode(),
                    clearFundResBO.getErrorMsg(), clearFundResBO.getResponseDate(), clearFundResBO.getResponseNo(),
                    requestOrderNo, false);
        }
        PayStatusEnums status = PayStatusEnums.explain(clearFundResBO.getPayStat());
        switch (status) {
            case FAIL:
                if (checkClearAmt(withdrawBO.getAmt(), clearFundResBO.getAmt())) {
                    return new ResponseBO(PayStatusEnums.INIT.getCode(), PayCoreErrorCode.AMT_IS_NOT_IN_CONFORMITY.getErrorCode(),
                            PayCoreErrorCode.AMT_IS_NOT_IN_CONFORMITY.getErrorDesc(), new Date(), null, requestOrderNo, false);
                }
                this.failFundProcess(withdrawBO, true);
                reStore(withdrawBO);
                //异步插入dispatch,做解冻处理
                this.addBizCmd(withdrawBO.getPayNo(), withdrawBO.getServiceCode(),
                        BizCmdTypeEnum.ACC_UNFREEZE.getCode(), 1);
                return new ResponseBO(PayStatusEnums.FAIL.getCode(), clearFundResBO.getErrorCode(),
                        clearFundResBO.getErrorMsg(), new Date(), null, requestOrderNo, true);
            case SUCCESS:
                if (checkClearAmt(withdrawBO.getAmt(), clearFundResBO.getAmt())) {
                    return new ResponseBO(PayStatusEnums.INIT.getCode(), PayCoreErrorCode.AMT_IS_NOT_IN_CONFORMITY.getErrorCode(),
                            PayCoreErrorCode.AMT_IS_NOT_IN_CONFORMITY.getErrorDesc(), new Date(), null, requestOrderNo, false);
                }
                //更新清分提现单状态
                withdrawBO.getWithdrawBankBO().setStatus(PayStatusEnums.SUCCESS.getCode());
                //推进订单
                advance(withdrawBO, clearFundResBO.getEventNo());
                reStore(withdrawBO);
                return new ResponseBO(withdrawBO.getStatus(), withdrawBO.getErrorCode(),
                        withdrawBO.getErrorMsg(), clearFundResBO.getResponseDate(), clearFundResBO.getResponseNo(),
                        requestOrderNo, true);
            default:
                return new ResponseBO(PayStatusEnums.INIT.getCode(), clearFundResBO.getErrorCode(),
                        clearFundResBO.getErrorMsg(), clearFundResBO.getResponseDate(), clearFundResBO.getResponseNo(),
                        requestOrderNo, false);
        }

    }

    private boolean checkClearAmt(Long withdrawAmt, Long clearAmt) {

        return !withdrawAmt.equals(clearAmt);
    }

}
